package dao

import (
	"fmt"
	"strings"
	"sync"
	"time"
	"yundian/internel/app/helper"
	"yundian/internel/app/helper/request"
	"yundian/internel/app/models/agentincome"
	"yundian/internel/app/models/internalstatistics"
	"yundian/internel/app/models/placeincome"
	"yundian/internel/app/models/placemodel"
	"yundian/internel/pkg/dingo"
	"yundian/internel/pkg/dingo/global"
	"yundian/internel/pkg/utils"
)

// SetPlacePushDataListStatusSuccess 推送数据成功状态设置
func (d *StatisticalDao) SetPlacePushDataListStatusSuccess(orders []string) *dingo.ErrorWrap {
	db := global.Orm.Table("gpp_place_settlement gps")
	db.Where("original_order IN ?", orders)
	db.Update("status", helper.TypeNumGppPlaceSettlementSuccess)

	return dingo.ErrorIf(db.Error)
}

// SetPlacePushDataListStatusFail 推送数据失败状态设置
func (d *StatisticalDao) SetPlacePushDataListStatusFail(orders []string) *dingo.ErrorWrap {
	db := global.Orm.Table("gpp_place_settlement gps")
	db.Where("original_order IN ?", orders)
	db.Update("status", helper.TypeNumGppPlaceSettlementFail)

	return dingo.ErrorIf(db.Error)
}

// GetPlaceWaitPushDataList 查询待推送数据
func (d *StatisticalDao) GetPlaceWaitPushDataList(param *request.SendPlacePushDataReq) *dingo.ErrorWrap {
	var dbList []*placemodel.GppPlaceSettlementDb

	db := global.Orm.Table("gpp_place_settlement gps").Select(`gps.*`)
	//db.Joins("LEFT JOIN places p ON gps.place_id=p.id")
	//db.Where("project_label=?", param.ProjectLabel)
	db.Where("gps.status IN ?", []int{helper.TypeNumGppPlaceSettlementWait, helper.TypeNumGppPlaceSettlementFail})
	db.Where("gps.settlement_money>0")

	if param.Month != "" {
		db.Where("gps.month=?", param.Month)
	}

	db.Order("gps.update_time DESC")
	db.Find(&dbList)

	return dingo.ErrorIf(db.Error, dbList)
}

// 查询已推送的
func (d *StatisticalDao) GetPlaceWaitPushDataListByZm(param *request.SendPlacePushDataReq) *dingo.ErrorWrap {
	var dbList []*placemodel.GppPlaceSettlementDb

	db := global.Orm.Table("gpp_place_settlement gps").Select(`gps.*`)
	db.Joins("LEFT JOIN places p ON gps.place_id=p.id")
	db.Where("project_label=?", param.ProjectLabel)
	db.Where("gps.status IN ?", []int{helper.TypeNumGppPlaceSettlementWait})

	if param.Month != "" {
		db.Where("gps.month=?", param.Month)
	}

	db.Order("gps.update_time DESC")
	db.Find(&dbList)

	return dingo.ErrorIf(db.Error, dbList)
}

// GetPlacePushDataList 查询推送数据
func (d *StatisticalDao) GetPlacePushDataList(param *request.GetPlacePushDataListReq) *dingo.ErrorWrap {
	var (
		lst    []*request.GetPlacePushDataListRes
		count  int64
		limit  int = param.PageSize
		offset int = param.PageSize * (param.PageNo - 1)
	)

	fields := `gps.*,DATE_FORMAT(gps.create_time, '%Y-%m-%d %T')create_time,DATE_FORMAT
	(gps.update_time, '%Y-%m-%d %T')update_time,p.place_name`
	db := global.Orm.Table("gpp_place_settlement gps").Select(fields)
	db.Joins("LEFT JOIN places p ON gps.place_id=p.id")
	db.Where("project_label=?", param.ProjectLabel)

	if param.Status > 0 {
		db.Where("gps.status=?", param.Status)
	}
	if param.PlaceId > 0 {
		db.Where("gps.place_id=?", param.ParentId)
	}
	if param.Month != "" {
		db.Where("gps.month=?", param.Month)
	}

	db.Order("gps.id DESC")
	db.Limit(limit).Offset(offset).Find(&lst).Limit(-1).Offset(-1).Count(&count)

	return dingo.ErrorIf(db.Error, lst, count)
}

func (d *StatisticalDao) GetGppPlaceIncomeOrderMonthListInHotelId(param *request.CreateGppPlacePushDataReq) *dingo.ErrorWrap {
	var dbList []*placemodel.GppPlaceSettlementDb

	fields := `SUM(IF(DATE_FORMAT(FROM_UNIXTIME(o.end_at),'%Y-%m')=? AND o.is_draw=0 AND o.state=5, 1, 0)) order_count,
	SUM(IF(DATE_FORMAT(FROM_UNIXTIME(o.end_at),'%Y-%m')=? AND o.is_draw=0 AND o.state=5, o.settlement_money, 0)) 
	settlement_money,p.hotel_id,pbrc.cost_amount, gps.status,pbrc.proportion,p.id place_id,? month`
	db := global.Orm.Table("places p").Select(fields, param.Month, param.Month, param.Month)
	db.Joins("LEFT JOIN orders o ON o.place_id=p.id")
	db.Joins("LEFT JOIN place_brand_relevancy_config pbrc ON pbrc.place_id=p.id AND pbrc.project_key=p.project_label")
	db.Joins("LEFT JOIN gpp_place_settlement gps ON gps.place_id=p.id AND gps.month=?", param.Month)
	db.Where(`pbrc.project_key=?`, param.ProjectLabel)

	if param.ParentId > 0 {
		db.Where("p.id=?", param.PlaceId)
	}

	db.Group(`p.id`).Find(&dbList)
	return dingo.ErrorIf(db.Error, dbList)
}

// CreateGppPlacePushDataInMonth 生成推送数据-按月份
func (d *StatisticalDao) CreateGppPlacePushDataInMonth(param *request.CreateGppPlacePushDataReq) *dingo.ErrorWrap {
	placeIncomeData := d.GetGppPlaceIncomeOrderMonthListInHotelId(param)
	placeList := placeIncomeData.Unwrap().([]*placemodel.GppPlaceSettlementDb)
	if placeIncomeData.Err != nil || len(placeList) == 0 {
		return dingo.ErrorIf(placeIncomeData.Err)
	}

	var dbInsertParams []interface{}
	sql := `INSERT INTO gpp_place_settlement(place_id, settlement_money, order_count, 
	cost_amount, proportion, hotel_id, original_order, status, type, month) VALUES`
	for index, item := range placeList {
		if item.Status == helper.TypeNumGppPlaceSettlementSuccess {
			continue
		}

		if item.Status == 0 {
			n := utils.Join(global.Const.Pre.OrderPre, time.Now().Format("20060102150405"), utils.GetRandomInt(6))
			item.OriginalOrder = fmt.Sprintf("%d%s", item.PlaceId, n)
			item.Status = helper.TypeNumGppPlaceSettlementWait
		}
		item.Type = 1
		targetParams := []interface{}{
			item.PlaceId, item.SettlementMoney, item.OrderCount, item.CostAmount, item.Proportion,
			item.HotelId, item.OriginalOrder, item.Status, item.Type, item.Month,
		}
		dbInsertParams = append(dbInsertParams, targetParams...)
		sql += `(?,?,?,?,?,?,?,?,?,?)` + utils.AddStrJudge(index == (len(placeList)-1), ",")
	}
	sql += `ON DUPLICATE KEY UPDATE settlement_money=VALUES(settlement_money),order_count=VALUES(order_count)`
	db := global.Orm.Exec(sql, dbInsertParams...)
	return dingo.ErrorIf(db.Error)
}

func (d *StatisticalDao) GetGppPlaceIncomeOrderMonthList(param *placeincome.GetGppPlaceIncomeListReq) *dingo.ErrorWrap {
	var dbList []*placeincome.GetGppPlaceIncomeMonthListRes

	fields := `COUNT(1)order_count,SUM(settlement_money)settlement_money,
	o.place_id,DATE_FORMAT(FROM_UNIXTIME(o.end_at),'%Y-%m')date_str`
	db := global.Orm.Table("orders o").Select(fields)
	db.Joins("LEFT JOIN places p ON o.place_id=p.id")
	db.Where(`o.is_draw=0 AND o.state=5 AND p.hotel_id=? AND project_label=?`, param.HotelId, param.ProjectLabel)
	db.Where("DATE_FORMAT(FROM_UNIXTIME(o.end_at),'%Y')=?", param.Year)
	db.Group(`o.place_id,date_str`).Find(&dbList)
	return dingo.ErrorIf(db.Error, dbList)
}

func (d *StatisticalDao) GetGppPlaceIncomeMonthList(param *placeincome.GetGppPlaceIncomeListReq) *dingo.ErrorWrap {
	var dbList []*placeincome.GetGppPlaceIncomeMonthListRes

	fields := `pi.place_id,SUM(IF(pi.id=pi1.id,pi.device_total,0))device_count,
	LEFT(pi.income_day,7) date_str,p.place_name,p.hotel_id,pbrc.proportion,pbrc.cost_amount`
	db := global.Orm.Table("place_income pi").Select(fields)
	db.Joins("LEFT JOIN places p ON pi.place_id=p.id")
	db.Joins("LEFT JOIN place_brand_relevancy_config pbrc ON pbrc.place_id=pi.place_id")
	db.Joins("LEFT JOIN (SELECT MAX(id)id FROM place_income GROUP BY place_id,LEFT(income_day,7)) pi1 ON pi.id=pi1.id")
	db.Where(`p.hotel_id=? AND LEFT(pi.income_day, 4)=? AND p.project_label=?`, param.HotelId, param.Year, param.ProjectLabel)
	db.Order("pi.income_day DESC").Find(&dbList)
	return dingo.ErrorIf(db.Error, dbList)
}

// GetGppOrderDayMonthListByHotelId 门店按月份统计
func (d *StatisticalDao) GetGppOrderDayMonthListByHotelId(param *placeincome.GetGppPlaceIncomeListReq) *dingo.ErrorWrap {
	placeIncomeData := d.GetGppPlaceIncomeMonthList(param)
	placeIncomeList := placeIncomeData.Unwrap().([]*placeincome.GetGppPlaceIncomeMonthListRes)
	if placeIncomeData.Err != nil {
		return dingo.ErrorIf(placeIncomeData.Err, placeIncomeList)
	}

	if len(placeIncomeList) > 0 {
		placeIncomeOrderData := d.GetGppPlaceIncomeOrderMonthList(param)
		placeIncomeOrderList := placeIncomeOrderData.Unwrap().([]*placeincome.GetGppPlaceIncomeMonthListRes)
		if placeIncomeOrderData.Err != nil {
			return dingo.ErrorIf(placeIncomeOrderData.Err, placeIncomeOrderList)
		}

		for _, item := range placeIncomeList {
			for _, oItem := range placeIncomeOrderList {
				if item.Date == oItem.Date && item.PlaceId == oItem.PlaceId {
					item.SettlementMoney = oItem.SettlementMoney
					item.OrderCount = oItem.OrderCount

					// 整体费用
					if item.SettlementMoney > 0 && item.SettlementMoney <= item.CostAmount {
						item.ProportionFee = item.CostAmount
					} else if item.SettlementMoney > item.CostAmount {
						item.ProportionFee = int64(float64(item.SettlementMoney-item.CostAmount) * item.Proportion / 100)
					}
					break
				}
			}
		}
	}

	return dingo.ErrorIf(nil, placeIncomeList)
}

func (d *StatisticalDao) GetGppPlaceIncomeList(param *placeincome.GetGppPlaceIncomeListReq) *dingo.ErrorWrap {
	var dbList []*placeincome.GetGppPlaceIncomeListRes

	fields := `pi.place_id,pi.device_total,device_count,pi.income_day date_str,p.place_name,p.hotel_id,pbrc.proportion`
	db := global.Orm.Table("place_income pi").Select(fields)
	db.Joins("LEFT JOIN places p ON pi.place_id=p.id")
	db.Joins("LEFT JOIN place_brand_relevancy_config pbrc ON pbrc.place_id=pi.place_id")
	db.Where(`p.hotel_id=? AND LEFT(pi.income_day, 7)=? AND p.project_label=?`, param.HotelId, param.Month, param.ProjectLabel)
	db.Order("pi.income_day DESC").Find(&dbList)
	return dingo.ErrorIf(db.Error, dbList)
}

func (d *StatisticalDao) GetGppPlaceIncomeOrderList(param *placeincome.GetGppPlaceIncomeListReq) *dingo.ErrorWrap {
	var dbList []*placeincome.GetGppPlaceIncomeListRes

	fields := `COUNT(1)order_count,SUM(settlement_money)settlement_money,
	o.place_id,DATE_FORMAT(FROM_UNIXTIME(o.end_at),'%Y-%m-%d')date_str`
	db := global.Orm.Table("orders o").Select(fields)
	db.Joins("LEFT JOIN places p ON o.place_id=p.id")
	db.Where(`o.is_draw=0 AND o.state=5 AND p.hotel_id=? AND project_label=?`, param.HotelId, param.ProjectLabel)
	db.Where("DATE_FORMAT(FROM_UNIXTIME(o.end_at),'%Y-%m')=?", param.Month)
	db.Group(`o.place_id,date_str`).Find(&dbList)
	return dingo.ErrorIf(db.Error, dbList)
}

func (d *StatisticalDao) GetGppOrderDayDataListByHotelId(param *placeincome.GetGppPlaceIncomeListReq) *dingo.ErrorWrap {
	placeIncomeData := d.GetGppPlaceIncomeList(param)
	placeIncomeList := placeIncomeData.Unwrap().([]*placeincome.GetGppPlaceIncomeListRes)
	if placeIncomeData.Err != nil {
		return dingo.ErrorIf(placeIncomeData.Err, placeIncomeList)
	}

	if len(placeIncomeList) > 0 {
		placeIncomeOrderData := d.GetGppPlaceIncomeOrderList(param)
		placeIncomeOrderList := placeIncomeOrderData.Unwrap().([]*placeincome.GetGppPlaceIncomeListRes)
		if placeIncomeOrderData.Err != nil {
			return dingo.ErrorIf(placeIncomeOrderData.Err, placeIncomeOrderList)
		}

		for _, item := range placeIncomeList {
			for _, oItem := range placeIncomeOrderList {
				if item.Date == oItem.Date && item.PlaceId == oItem.PlaceId {
					item.SettlementMoney = oItem.SettlementMoney
					item.OrderCount = oItem.OrderCount
					break
				}
			}
		}
	}

	return dingo.ErrorIf(nil, placeIncomeList)
}

// 代理商统计
func (d *StatisticalDao) AgentIncomeDayStatisticsListDao(params *request.AgentStatisticsReportReq) *dingo.ErrorWrap {
	var data *dingo.ErrorWrap
	if params.MonthType == helper.TypeNumDateTypeMonth {
		data = d.AgentIncomeMonthStatisticsQuery(params)
	} else {
		data = d.AgentIncomeDayStatisticsQuery(params)
	}
	list := data.Unwrap().([]*agentincome.AgentIncomeModel)

	if len(list) == 0 {
		return dingo.ErrorIf(data.Err, list, data.Val())
	}

	var userIds []int
	var dates []string
	for _, item := range list {
		userIds = append(userIds, item.AgentUserId)
		dates = append(dates, item.IncomeDay)
	}

	sw := sync.WaitGroup{}
	sw.Add(2)
	userIds = utils.ToIntRepetition(userIds)
	dates = utils.ToStrRepetition(dates)
	var dividendsList []*StatisticsOrderDividends
	var orderList []*StatisticsOrderDividends
	go func() {
		dividendsList, _ = d.AgentIncomeStatisticsListDividends(userIds, dates, uint8(params.MonthType))
		sw.Done()
	}()
	go func() {
		orderList, _ = d.AgentIncomeStatisticsListOrder(userIds, dates, params)
		sw.Done()
	}()
	sw.Wait()
	for _, item1 := range list {
		for _, item := range dividendsList {
			if item.IncomeDay == item1.IncomeDay && item.UserId == item1.AgentUserId {
				item1.DivindsMoney = item.TotalMoney
				item1.TotalMoney = item.TotalMoney
				break
			}
		}
		for _, item := range orderList {
			if item.IncomeDay == item1.IncomeDay && item.UserId == item1.AgentUserId {
				item1.TradeTotal = item.TradeTotal
				item1.CancelCount = item.CancelCount
				item1.CompleteCount = item.CompleteCount
				break
			}
		}
	}

	return dingo.ErrorIf(data.Err, list, data.Val())
}

//代理商总统计
//func (d *StatisticalDao) AgentIncomeDayStatisticsAllListDao(params *request.AgentStatisticsReportReq) *dingo.ErrorWrap {
//	var data *dingo.ErrorWrap
//	data = d.AgentIncomeAllStatisticsExportQuery(params)
//	list := data.Unwrap().([]*agentincome.AgentIncomeModel)
//
//	if len(list) == 0 {
//		return dingo.ErrorIf(data.Err, list, data.Val())
//	}
//
//	var userIds []int
//	var dates []string
//	for _, item := range list {
//		userIds = append(userIds, item.AgentUserId)
//		dates = append(dates, item.IncomeDay)
//	}
//
//	sw := sync.WaitGroup{}
//	sw.Add(2)
//	userIds = utils.ToIntRepetition(userIds)
//	dates = utils.ToStrRepetition(dates)
//	var dividendsList []*StatisticsOrderDividends
//	var orderList []*StatisticsOrderDividends
//	if params.MonthType == 3 {
//
//		go func() {
//			dividendsList, _ = d.AgentIncomeStatisticsListDividendsAll()
//			sw.Done()
//		}()
//		go func() {
//			orderList, _ = d.AgentIncomeStatisticsListOrderAllQuery(params, userIds)
//			sw.Done()
//		}()
//		sw.Wait()
//	}
//	//总查询，只比较用户
//	if params.MonthType == 3 {
//		for _, item1 := range list {
//			for _, item := range dividendsList {
//				if item.UserId == item1.AgentUserId {
//					item1.DivindsMoney = item.TotalMoney
//					item1.TotalMoney = item.TotalMoney
//					break
//				}
//			}
//			for _, item := range orderList {
//				if item.UserId == item1.AgentUserId {
//					item1.TradeTotal = item.TradeTotal
//					item1.CancelCount = item.CancelCount
//					item1.CompleteCount = item.CompleteCount
//					break
//				}
//			}
//		}
//	}
//
//	return dingo.ErrorIf(data.Err, list, data.Val())
//}

// 代理商统计 日统计表查询
func (d *StatisticalDao) AgentIncomeDayStatisticsQuery(params *request.AgentStatisticsReportReq) *dingo.ErrorWrap {
	var (
		count  int64
		list   []*agentincome.AgentIncomeModel
		limit  = params.PageSize
		offset = params.PageSize * (params.PageNo - 1)
	)
	fields := `a.*,a.total_orders order_count,a.total_cancel cancel_count,a.total_complete complete_count,a.user_id 
	agent_user_id,a.total_place places_total,a.total_devices device_total,a.date_str income_day,
	u.name as name,u.user_name as agent_user_name,u.phone as phone`
	db := global.Orm.Debug().Table("statistics_user a").Select(fields).
		Joins("LEFT JOIN users u ON a.user_id = u.id")

	if params.UserId > 0 {
		db.Where("a.user_id = ?", params.UserId)
	}

	if params.SharedMode != "" {
		db.Where("a.shared_mode=?", params.SharedMode)
	}

	if params.SelectTime != "" {
		selectTimeArr := strings.Split(params.SelectTime, ",")
		startTime := selectTimeArr[0]
		endTime := selectTimeArr[1]
		db.Where("a.date_str >= DATE_FORMAT(FROM_UNIXTIME(?),'%Y-%m-%d')", startTime)
		db.Where("a.date_str <= DATE_FORMAT(FROM_UNIXTIME(?),'%Y-%m-%d')", endTime)
	}

	if params.LoginUserId != 2 {
		userIdArr := NewUserDao().QueryChildUserIds(params.LoginUserId).Unwrap().([]int)
		db.Where("a.user_id in (?)", userIdArr)
	}

	db.Order("a.date_str desc")
	db.Limit(limit).Offset(offset).Find(&list).Limit(-1).Offset(-1).Count(&count)

	return dingo.ErrorIf(db.Error, list, count)
}

// 代理商统计 月统计表查询
func (d *StatisticalDao) AgentIncomeMonthStatisticsQuery(params *request.AgentStatisticsReportReq) *dingo.ErrorWrap {
	var (
		count  int64
		list   []*agentincome.AgentIncomeModel
		limit  = params.PageSize
		offset = params.PageSize * (params.PageNo - 1)
	)

	//fields := `a.id,a.agent_user_id,DATE_FORMAT(income_day, '%Y-%m')income_day,a.agent_user_id,
	//a.places_total,u.name as name,u.user_name as agent_user_name,u.phone as phone`
	fields := `a.*,a.total_orders order_count,a.total_cancel cancel_count,a.total_complete complete_count,a.user_id 
	agent_user_id,a.total_place places_total,a.total_devices device_total,DATE_FORMAT(a.date_str, '%Y-%m')income_day,
	u.name as name,u.user_name as agent_user_name,u.phone as phone`
	db := global.Orm.Table("statistics_user a").Select(fields).Joins("LEFT JOIN users u ON a.user_id = u.id").
		Joins("LEFT JOIN (SELECT MAX(id)id FROM statistics_user GROUP BY DATE_FORMAT(date_str, '%Y-%m'),user_id)ai1 ON a.id=ai1.id").
		Where("ai1.id>0")

	if params.UserId > 0 {
		db.Where("a.user_id = ?", params.UserId)
	}

	if params.SharedMode != "" {
		db.Where("a.shared_mode=?", params.SharedMode)
	}

	if params.SelectTime != "" {
		selectTimeArr := strings.Split(params.SelectTime, ",")
		startTime := selectTimeArr[0]
		endTime := selectTimeArr[1]
		db.Where("a.date_str >= DATE_FORMAT(FROM_UNIXTIME(?),'%Y-%m-%d')", startTime)
		db.Where("a.date_str <= DATE_FORMAT(FROM_UNIXTIME(?),'%Y-%m-%d')", endTime)
	}

	if params.LoginUserId != 2 {
		userIdArr := NewUserDao().QueryChildUserIds(params.LoginUserId).Unwrap().([]int)
		db.Where("a.user_id in (?)", userIdArr)
	}

	db.Order("a.date_str desc")
	db.Limit(limit).Offset(offset).Find(&list).Limit(-1).Offset(-1).Count(&count)

	return dingo.ErrorIf(db.Error, list, count)
}

// 代理商统计 分红查询
func (d *StatisticalDao) AgentIncomeStatisticsListDividends(userIds []int, dates []string, dateType uint8) (list []*StatisticsOrderDividends, err error) {
	incomeDay := fmt.Sprintf(`DATE_FORMAT(dl.end_date,'%s')`, "%Y-%m-%d")
	groupDate := `dl.end_date`
	maxDivision := 2
	if dateType == helper.TypeNumDateTypeMonth {
		incomeDay = fmt.Sprintf(`dl.end_month`)
		groupDate = `dl.end_month`
		maxDivision = 1
	}

	type w struct {
		SW  sync.WaitGroup
		Err []error
	}
	sw := &w{}
	dateMap := utils.ToStrArrDivision(dates, maxDivision)
	for _, dateArr := range dateMap {
		sw.SW.Add(1)
		go func(dateArr []string, sw *w) {
			var targetList []*StatisticsOrderDividends
			sql := fmt.Sprintf(`SELECT SUM(dl.money) total_money,dl.user_id,dl.place_id,%s 
			as income_day FROM dividends_log dl WHERE dl.user_id IN (?) AND %s IN (?) GROUP BY %s,dl.user_id`,
				incomeDay, groupDate, groupDate)
			if db := global.Orm.Raw(sql, userIds, dateArr).Find(&targetList); db.Error != nil {
				sw.Err = append(sw.Err, db.Error)
			}
			list = append(list, targetList...)
			sw.SW.Done()
		}(dateArr, sw)
	}
	sw.SW.Wait()
	if len(sw.Err) > 0 {
		err = sw.Err[0]
	}

	//sql := fmt.Sprintf(`SELECT SUM(dl.money) total_money,dl.user_id,dl.place_id,DATE_FORMAT(%s,'%s') as income_day
	//FROM dividends_log dl WHERE dl.user_id IN (?) AND %s IN (?) GROUP BY %s,dl.user_id;`, groupDate, groupDateStr, groupDate, groupDate)
	//db := global.Orm.Debug().Raw(sql, userIds, dates).Find(&list)

	return list, err
}

// 代理商统计 订单查询
func (d *StatisticalDao) AgentIncomeStatisticsListOrder(userIds []int, dates []string, params *request.AgentStatisticsReportReq) (list []*StatisticsOrderDividends, err error) {
	incomeDay := fmt.Sprintf(`DATE_FORMAT(our.end_date,'%s')`, "%Y-%m-%d")
	selectOrderSql := ``
	groupDate := `our.end_date`
	maxDivision := 2
	if params.MonthType == helper.TypeNumDateTypeMonth {
		incomeDay = fmt.Sprintf(`our.end_month`)
		groupDate = `our.end_month`
		maxDivision = 1
	}

	if params.IsAdmin != helper.TypeNumIsAdminOperator || params.LoginUserId != params.UserId {
		selectOrderSql = fmt.Sprintf(`AND is_tianhai=0 AND (o.is_draw<>1 or (o.is_draw=1 and o.agent_user_id=%d))`, params.UserId)
	}

	type w struct {
		SW  sync.WaitGroup
		Err []error
	}
	sw := &w{}
	dateMap := utils.ToStrArrDivision(dates, maxDivision)
	for _, dateArr := range dateMap {
		sw.SW.Add(1)
		go func(dateArr []string, sw *w) {
			var targetList []*StatisticsOrderDividends
			sql := fmt.Sprintf(`SELECT our.user_id,SUM(IF(o.state=5,o.settlement_money,0))trade_total,
			SUM(IF(o.state=5,1,0))complete_count,SUM(IF(o.state=3,1,0))cancel_count,%s income_day 
			FROM orders o LEFT JOIN orders_user_relevancy our on o.trade_no = our.trade_no WHERE o.user_id > 0 and our.user_id IN (?) 
			AND %s IN(?) %s GROUP BY %s, our.user_id`, incomeDay, groupDate, selectOrderSql, groupDate)
			if db := global.Orm.Debug().Raw(sql, userIds, dateArr).Find(&targetList); db.Error != nil {
				sw.Err = append(sw.Err, db.Error)
			}
			list = append(list, targetList...)
			sw.SW.Done()
		}(dateArr, sw)
	}
	sw.SW.Wait()
	if len(sw.Err) > 0 {
		err = sw.Err[0]
	}

	//sql := fmt.Sprintf(`SELECT our.user_id,SUM(IF(o.state=5,o.settlement_money,0))trade_total,SUM(IF(o.state=5,1,0))
	//complete_count,SUM(IF(o.state=3,1,0))cancel_count,DATE_FORMAT(%s, '%s') income_day FROM orders o LEFT JOIN orders_user_relevancy our on
	//o.trade_no = our.trade_no WHERE our.user_id IN (?) AND %s IN(?) GROUP BY %s, our.user_id`, groupDate, groupDateStr, groupDate, groupDate)
	//db := global.Orm.Debug().Raw(sql, userIds, dates).Find(&list)

	return list, err
}

// 分公司统计
func (d *StatisticalDao) BranchIncomeDayStatisticsListDao(params *request.AgentStatisticsReportReq) *dingo.ErrorWrap {
	var data *dingo.ErrorWrap
	if params.MonthType == helper.TypeNumDateTypeMonth {
		data = d.BranchIncomeMonthStatisticsQuery(params)
	} else {
		data = d.BranchIncomeDayStatisticsQuery(params)
	}
	list := data.Unwrap().([]*agentincome.BranchIncomeModel)

	if len(list) == 0 {
		return dingo.ErrorIf(data.Err, list, data.Val())
	}

	var userIds []int
	var dates []string
	for _, item := range list {
		userIds = append(userIds, item.BranchUserId)
		dates = append(dates, item.IncomeDay)
	}

	sw := sync.WaitGroup{}
	sw.Add(2)
	userIds = utils.ToIntRepetition(userIds)
	dates = utils.ToStrRepetition(dates)
	var dividendsList []*StatisticsOrderDividends
	var orderList []*StatisticsOrderDividends
	go func() {
		dividendsList, _ = d.AgentIncomeStatisticsListDividends(userIds, dates, uint8(params.MonthType))
		sw.Done()
	}()
	go func() {
		orderList, _ = d.AgentIncomeStatisticsListOrder(userIds, dates, params)
		sw.Done()
	}()
	sw.Wait()
	for _, item1 := range list {
		for _, item := range dividendsList {
			if item.IncomeDay == item1.IncomeDay && item.UserId == item1.BranchUserId {
				item1.DivindsMoney = item.TotalMoney
				item1.TotalMoney = item.TotalMoney
				break
			}
		}
		for _, item := range orderList {
			if item.IncomeDay == item1.IncomeDay && item.UserId == item1.BranchUserId {
				item1.TradeTotal = item.TradeTotal
				item1.CancelCount = item.CancelCount
				item1.CompleteCount = item.CompleteCount
				break
			}
		}
	}

	return dingo.ErrorIf(data.Err, list, data.Val())
}

// 分公司统计 日统计表查询
func (d *StatisticalDao) BranchIncomeDayStatisticsQuery(params *request.AgentStatisticsReportReq) *dingo.ErrorWrap {
	var (
		count  int64
		list   []*agentincome.BranchIncomeModel
		limit  = params.PageSize
		offset = params.PageSize * (params.PageNo - 1)
	)
	db := global.Orm.Debug().Table("branch_income a")

	if params.UserId > 0 {
		db.Where("a.agent_user_id = ?", params.UserId)
	}

	if params.SharedMode != "" {
		db.Where("a.shared_mode=?", params.SharedMode)
	}

	if params.SelectTime != "" {
		selectTimeArr := strings.Split(params.SelectTime, ",")
		startTime := selectTimeArr[0]
		endTime := selectTimeArr[1]
		db.Where("a.income_day >= DATE_FORMAT(FROM_UNIXTIME(?),'%Y-%m-%d')", startTime)
		db.Where("a.income_day <= DATE_FORMAT(FROM_UNIXTIME(?),'%Y-%m-%d')", endTime)
	}

	if params.IsAdmin != helper.TypeNumIsAdminOperator {
		userIdArr := NewUserDao().QueryChildUserIds(params.LoginUserId).Unwrap().([]int)
		db.Where("a.agent_user_id in (?)", userIdArr)
	}

	db.Order("a.income_day desc")
	db.Limit(limit).Offset(offset).Find(&list).Limit(-1).Offset(-1).Count(&count)

	return dingo.ErrorIf(db.Error, list, count)
}

// 分公司统计 月统计表查询
func (d *StatisticalDao) BranchIncomeMonthStatisticsQuery(params *request.AgentStatisticsReportReq) *dingo.ErrorWrap {
	var (
		count  int64
		list   []*agentincome.BranchIncomeModel
		limit  = params.PageSize
		offset = params.PageSize * (params.PageNo - 1)
	)

	fields := `a.id,a.agent_user_id,DATE_FORMAT(income_day, '%Y-%m')income_day,a.agent_user_id,a.places_total,a.agent_user_name`
	db := global.Orm.Debug().Table("branch_income a").
		Select(fields).Joins("LEFT JOIN users u ON a.agent_user_id = u.id").
		Joins("LEFT JOIN (SELECT MAX(id)id FROM branch_income GROUP BY DATE_FORMAT(income_day, '%Y-%m'),agent_user_id)ai1 ON a.id=ai1.id").
		Where("ai1.id>0")

	if params.UserId > 0 {
		db.Where("a.agent_user_id = ?", params.UserId)
	}

	if params.SharedMode != "" {
		db.Where("a.shared_mode=?", params.SharedMode)
	}

	if params.SelectTime != "" {
		selectTimeArr := strings.Split(params.SelectTime, ",")
		startTime := selectTimeArr[0]
		endTime := selectTimeArr[1]
		db.Where("a.income_day >= DATE_FORMAT(FROM_UNIXTIME(?),'%Y-%m-%d')", startTime)
		db.Where("a.income_day <= DATE_FORMAT(FROM_UNIXTIME(?),'%Y-%m-%d')", endTime)
	}

	if params.IsAdmin != helper.TypeNumIsAdminOperator {
		userIdArr := NewUserDao().QueryChildUserIds(params.LoginUserId).Unwrap().([]int)
		db.Where("a.agent_user_id in (?)", userIdArr)
	}

	db.Order("a.income_day desc")
	db.Limit(limit).Offset(offset).Find(&list).Limit(-1).Offset(-1).Count(&count)

	return dingo.ErrorIf(db.Error, list, count)
}

type StatisticsOrderDividends struct {
	IncomeDay     string `gorm:"column:income_day" json:"incomeDay"`          // 天
	UserId        int    `gorm:"column:user_id" json:"userId"`                // 用户ID
	TotalMoney    int64  `gorm:"column:total_money" json:"totalMoney"`        // 总收益
	TradeTotal    int64  `gorm:"column:trade_total" json:"tradeTotal"`        // 交易总额
	CompleteCount int64  `gorm:"column:complete_count" json:"completeCount"`  // 完成条数
	CancelCount   int64  `gorm:"column:cancel_count" json:"cancelCount"`      // 取消条数
	EarningsMoney int64  `gorm:"column:earnings_money" json:"earnings_money"` // 运营商收益
}

//项目日统计
func (d *StatisticalDao) DayStatisticsQuery(params *request.ProjectStatisticsReq) *dingo.ErrorWrap {
	var (
		count  int64
		list   []*agentincome.AgentIncomeModel
		limit  = params.PageSize
		offset = params.PageSize * (params.PageNo - 1)
	)
	db := global.Orm.Debug().Table("agent_income a").
		Select("a.*,u.name as name,u.user_name as agent_user_name,u.phone as phone").
		Joins("LEFT JOIN users u ON a.agent_user_id = u.id").
		Where("u.is_admin = ?", params.IsAdmin)

	if params.UserId > 0 {
		db.Where("a.agent_user_id = ?", params.UserId)
	}

	if params.SharedMode != "" {
		db.Where("a.shared_mode=?", params.SharedMode)
	}

	if params.SelectTime != "" {
		selectTimeArr := strings.Split(params.SelectTime, ",")
		startTime := selectTimeArr[0]
		endTime := selectTimeArr[1]
		db.Where("a.income_day >= DATE_FORMAT(FROM_UNIXTIME(?),'%Y-%m-%d')", startTime)
		db.Where("a.income_day <= DATE_FORMAT(FROM_UNIXTIME(?),'%Y-%m-%d')", endTime)
	}

	if params.LoginIsAdmin != helper.TypeNumIsAdminOperator {
		userIdArr := NewUserDao().QueryChildUserIds(params.LoginUserId).Unwrap().([]int)
		db.Where("a.agent_user_id in (?)", userIdArr)
	}

	db.Order("a.income_day desc")
	db.Limit(limit).Offset(offset).Find(&list).Limit(-1).Offset(-1).Count(&count)

	return dingo.ErrorIf(db.Error, list, count)
}

//项目月统计
func (d *StatisticalDao) MonthStatisticsQuery(params *request.ProjectStatisticsReq) *dingo.ErrorWrap {
	var (
		count  int64
		list   []*agentincome.AgentIncomeModel
		limit  = params.PageSize
		offset = params.PageSize * (params.PageNo - 1)
	)

	fields := `a.id,a.agent_user_id,DATE_FORMAT(income_day, '%Y-%m')income_day,a.agent_user_id,
	a.places_total,u.name as name,u.user_name as agent_user_name,u.phone as phone`
	db := global.Orm.Debug().Table("agent_income a").Select(fields).Joins("LEFT JOIN users u ON a.agent_user_id = u.id").
		Joins("LEFT JOIN (SELECT MAX(id)id FROM agent_income GROUP BY DATE_FORMAT(income_day, '%Y-%m'),agent_user_id)ai1 ON a.id=ai1.id").
		Where("ai1.id>0").
		Where("u.is_admin = ?", params.IsAdmin)
	if params.UserId > 0 {
		db.Where("a.agent_user_id = ?", params.UserId)
	}

	if params.SharedMode != "" {
		db.Where("a.shared_mode=?", params.SharedMode)
	}

	if params.SelectTime != "" {
		selectTimeArr := strings.Split(params.SelectTime, ",")
		startTime := selectTimeArr[0]
		endTime := selectTimeArr[1]
		db.Where("a.income_day >= DATE_FORMAT(FROM_UNIXTIME(?),'%Y-%m-%d')", startTime)
		db.Where("a.income_day <= DATE_FORMAT(FROM_UNIXTIME(?),'%Y-%m-%d')", endTime)
	}

	if params.LoginIsAdmin != helper.TypeNumIsAdminOperator {
		userIdArr := NewUserDao().QueryChildUserIds(params.LoginUserId).Unwrap().([]int)
		db.Where("a.agent_user_id in (?)", userIdArr)
	}

	db.Order("a.income_day desc")
	db.Limit(limit).Offset(offset).Find(&list).Limit(-1).Offset(-1).Count(&count)

	return dingo.ErrorIf(db.Error, list, count)
}

// 统计 分红查询
func (d *StatisticalDao) StatisticsListDividends(userIds []int, dates []string, dateType uint8) (list []*StatisticsOrderDividends, err error) {
	incomeDay := fmt.Sprintf(`DATE_FORMAT(dl.end_date,'%s')`, "%Y-%m-%d")
	groupDate := `dl.end_date`
	maxDivision := 2
	if dateType == helper.TypeNumDateTypeMonth {
		incomeDay = fmt.Sprintf(`dl.end_month`)
		groupDate = `dl.end_month`
		maxDivision = 1
	}

	type w struct {
		SW  sync.WaitGroup
		Err []error
	}
	sw := &w{}
	dateMap := utils.ToStrArrDivision(dates, maxDivision)
	for _, dateArr := range dateMap {
		sw.SW.Add(1)
		go func(dateArr []string, sw *w) {
			var targetList []*StatisticsOrderDividends
			sql := fmt.Sprintf(`SELECT SUM(dl.money) total_money,dl.user_id,dl.place_id,%s
			as income_day FROM dividends_log dl WHERE dl.user_id IN (?) AND %s IN (?) GROUP BY %s,dl.user_id`,
				incomeDay, groupDate, groupDate)
			if db := global.Orm.Raw(sql, userIds, dateArr).Find(&targetList); db.Error != nil {
				sw.Err = append(sw.Err, db.Error)
			}
			list = append(list, targetList...)
			sw.SW.Done()
		}(dateArr, sw)
	}
	sw.SW.Wait()
	if len(sw.Err) > 0 {
		err = sw.Err[0]
	}

	//sql := fmt.Sprintf(`SELECT SUM(dl.money) total_money,dl.user_id,dl.place_id,DATE_FORMAT(%s,'%s') as income_day
	//FROM dividends_log dl WHERE dl.user_id IN (?) AND %s IN (?) GROUP BY %s,dl.user_id;`, groupDate, groupDateStr, groupDate, groupDate)
	//db := global.Orm.Debug().Raw(sql, userIds, dates).Find(&list)

	return list, err
}

// 统计 订单查询
func (d *StatisticalDao) StatisticsListOrder(userIds []int, dates []string, params *request.ProjectStatisticsReq) (list []*StatisticsOrderDividends, err error) {
	incomeDay := fmt.Sprintf(`DATE_FORMAT(our.end_date,'%s')`, "%Y-%m-%d")
	selectOrderSql := ``
	groupDate := `our.end_date`
	maxDivision := 2
	if params.MonthType == helper.TypeNumDateTypeMonth {
		incomeDay = fmt.Sprintf(`our.end_month`)
		groupDate = `our.end_month`
		maxDivision = 1
	}

	if params.LoginIsAdmin == helper.TypeNumIsAdminOperator && params.UserId > 0 {
		selectOrderSql = fmt.Sprintf(`AND is_tianhai=0 AND (o.is_draw<>1 or (o.is_draw=1 and o.agent_user_id=%d))`, params.UserId)
	} else {
		selectOrderSql = fmt.Sprintf(`AND is_tianhai=0 AND (o.is_draw<>1 or (o.is_draw=1 and o.agent_user_id in (?)))`)
	}

	type w struct {
		SW  sync.WaitGroup
		Err []error
	}
	sw := &w{}
	dateMap := utils.ToStrArrDivision(dates, maxDivision)
	for _, dateArr := range dateMap {
		sw.SW.Add(1)
		go func(dateArr []string, sw *w) {
			var targetList []*StatisticsOrderDividends
			sql := fmt.Sprintf(`SELECT our.user_id,SUM(IF(o.state=5,o.settlement_money,0))trade_total,
			SUM(IF(o.state=5,1,0))complete_count,SUM(IF(o.state=3,1,0))cancel_count,%s income_day
			FROM orders o LEFT JOIN orders_user_relevancy our on o.trade_no = our.trade_no WHERE our.user_id IN (?)
			AND %s IN(?) %s GROUP BY %s, our.user_id`, incomeDay, groupDate, selectOrderSql, groupDate)
			if db := global.Orm.Debug().Raw(sql, userIds, dateArr, userIds).Find(&targetList); db.Error != nil {
				sw.Err = append(sw.Err, db.Error)
			}
			list = append(list, targetList...)
			sw.SW.Done()
		}(dateArr, sw)
	}
	sw.SW.Wait()
	if len(sw.Err) > 0 {
		err = sw.Err[0]
	}

	return list, err
}

// 统计 运营商收益
func (d *StatisticalDao) StatisticsListEarnings(userIds []int, dateType, isAdmin uint8) (list []*StatisticsOrderDividends, err error) {
	incomeDay := fmt.Sprintf(`DATE_FORMAT(dl.end_date,'%s')`, "%Y-%m-%d")
	if dateType == helper.TypeNumDateTypeMonth {
		incomeDay = fmt.Sprintf(`DATE_FORMAT(dl.end_date,'%s')`, "%Y-%m")
	}

	type w struct {
		SW  sync.WaitGroup
		Err []error
	}
	sw := &w{}
	for _, userId := range userIds {
		sw.SW.Add(1)
		go func(userId int, sw *w) {
			var userIds, placeIds []int
			if isAdmin == helper.TypeNumIsAdminBranch {
				placesBranchIds := NewUserDao().GetPlacesId(userId).Unwrap().([]int)
				userIds := NewUserDao().QueryChildUserIds(userId).Unwrap().([]int)
				placeIdArr := NewPlaceDao().GetPlaceByIds(userIds).Unwrap().([]int)
				//合并网点
				placesBranchIds = append(placesBranchIds, placeIdArr...)
				//去重网点
				placeIds = utils.RemoveRepByMap(placesBranchIds)
			} else {
				//获取Id下的所有门店
				userIds = NewUserDao().QueryChildUserIds(userId).Unwrap().([]int)
				placeIds = NewPlaceDao().GetPlaceByIds(userIds).Unwrap().([]int)
			}

			var targetList []*StatisticsOrderDividends
			sql := fmt.Sprintf(`SELECT SUM(dl.money) earnings_money,dl.place_id,%s
			as income_day FROM dividends_log dl WHERE user_id  = 2 AND place_id in (?)  GROUP BY income_day`,
				incomeDay)
			if db := global.Orm.Raw(sql, placeIds).Find(&targetList); db.Error != nil {
				sw.Err = append(sw.Err, db.Error)
			}
			var earningsList []*StatisticsOrderDividends
			for _, v := range targetList {
				v.UserId = userId
				earningsList = append(earningsList, v)
			}

			list = append(list, earningsList...)
			sw.SW.Done()
		}(userId, sw)
	}
	sw.SW.Wait()
	if len(sw.Err) > 0 {
		err = sw.Err[0]
	}

	return list, err
}

//项目统计
func (d *StatisticalDao) ProjectDayStatisticsList(params *request.ProjectStatisticsReq) *dingo.ErrorWrap {
	var data *dingo.ErrorWrap
	if params.MonthType == helper.TypeNumDateTypeMonth {
		data = d.MonthStatisticsQuery(params)
	} else {
		data = d.DayStatisticsQuery(params)
	}
	list := data.Unwrap().([]*agentincome.AgentIncomeModel)

	if len(list) == 0 {
		return dingo.ErrorIf(data.Err, list, data.Val())
	}

	var userIds []int
	var dates []string
	for _, item := range list {
		userIds = append(userIds, item.AgentUserId)
		dates = append(dates, item.IncomeDay)
	}

	sw := sync.WaitGroup{}
	sw.Add(3)
	userIds = utils.ToIntRepetition(userIds)
	dates = utils.ToStrRepetition(dates)
	var dividendsList []*StatisticsOrderDividends
	var orderList []*StatisticsOrderDividends
	var earningsList []*StatisticsOrderDividends
	go func() {
		dividendsList, _ = d.StatisticsListDividends(userIds, dates, uint8(params.MonthType))
		sw.Done()
	}()
	go func() {
		orderList, _ = d.StatisticsListOrder(userIds, dates, params)
		sw.Done()
	}()
	go func() {
		earningsList, _ = d.StatisticsListEarnings(userIds, uint8(params.MonthType), params.IsAdmin)
		sw.Done()
	}()

	sw.Wait()
	for _, item1 := range list {
		for _, item := range dividendsList {
			if item.IncomeDay == item1.IncomeDay && item.UserId == item1.AgentUserId {
				item1.DivindsMoney = item.TotalMoney
				item1.TotalMoney = item.TotalMoney
				break
			}
		}
		for _, item := range orderList {
			if item.IncomeDay == item1.IncomeDay && item.UserId == item1.AgentUserId {
				item1.TradeTotal = item.TradeTotal
				item1.CancelCount = item.CancelCount
				item1.CompleteCount = item.CompleteCount
				break
			}
		}
		for _, item := range earningsList {
			if item.IncomeDay == item1.IncomeDay && item.UserId == item1.AgentUserId {
				item1.EarningsMoney = item.EarningsMoney
				break
			}
		}

	}

	return dingo.ErrorIf(data.Err, list, data.Val())
}

func (d *StatisticalDao) GetStatisticsUserList() *dingo.ErrorWrap {
	var list []*internalstatistics.InternalStatistics
	fields := "id user_id,user_name,phone,is_admin"
	db := global.Orm.Debug().Table("users").Select(fields)
	db.Where("is_admin > 4")
	db.Find(&list)
	return dingo.ErrorIf(db.Error, list)
}

func (d *StatisticalDao) StatisticsMoneyList(userIds []int) ([]*internalstatistics.InternalStatistics, error) {

	var list []*internalstatistics.InternalStatistics
	var err error
	sql := fmt.Sprintf(`SELECT our.user_id,SUM(IF(o.state=5,o.settlement_money,0))money,
			our.end_month statistics_date
			FROM orders o LEFT JOIN orders_user_relevancy our on o.trade_no = our.trade_no WHERE our.user_id IN (?)
			and our.end_date = DATE_SUB( CURDATE( ), INTERVAL 0 DAY ) 
			AND is_tianhai=0 AND (o.is_draw<>1 or (o.is_draw=1 and o.agent_user_id in (?)))
			GROUP BY statistics_date, our.user_id`)
	db := global.Orm.Debug().Raw(sql, userIds, userIds).Find(&list)

	if db.Error != nil {
		err = db.Error
	}

	return list, err
}

func (d *StatisticalDao) StatisticsPlaceAndDeviceTotal(userIds []int) ([]*internalstatistics.InternalStatistics, error) {

	incomeDay := `DATE_FORMAT( income_day, '%Y-%m' ) statistics_date `

	var list []*internalstatistics.InternalStatistics

	var err error

	sql := fmt.Sprintf(`SELECT agent_user_id user_id,%s,places_total place_total,device_total
			FROM agent_income WHERE agent_user_id IN (?) And places_total >0 and income_day = DATE_SUB( CURDATE( ), INTERVAL 1 DAY )   GROUP BY statistics_date,user_id`, incomeDay)
	db := global.Orm.Debug().Raw(sql, userIds).Find(&list)

	if db.Error != nil {
		err = db.Error
	}

	return list, err
}

func (d *StatisticalDao) StatisticsPlacesNotEarnings(usersIds []int) ([]*internalstatistics.InternalStatistics, error) {
	var list []*internalstatistics.InternalStatistics
	var placeIds []int
	var err error
	sql := `SELECT p.id id   FROM places p LEFT JOIN orders o ON o.place_id = p.id 
				AND DATE_FORMAT( FROM_UNIXTIME( o.end_at ), '%Y-%m-%d' ) <= DATE_SUB( CURDATE( ), INTERVAL 30 DAY ) WHERE o.id IS NULL GROUP BY id`
	db := global.Orm.Raw(sql).Find(&placeIds)
	if db.Error != nil {
		return nil, db.Error
	}

	placeNotEarningsMap := map[int]string{}

	for _, placeId := range placeIds {
		placeNotEarningsMap[placeId] = ""
	}

	//查询没有收入的网点
	for _, id := range usersIds {
		var notIncomePlace int64
		model := &internalstatistics.InternalStatistics{}

		placesBranchIds := NewUserDao().GetPlacesId(id).Unwrap().([]int)
		userIds := NewUserDao().QueryChildUserIds(id).Unwrap().([]int)
		placeIdArr := NewPlaceDao().GetPlaceByIds(userIds).Unwrap().([]int)

		//合并网点
		placesBranchIds = append(placesBranchIds, placeIdArr...)

		//去重网点
		placesIds := utils.RemoveRepByMap(placesBranchIds)

		for _, placesId := range placesIds {
			if _, ok := placeNotEarningsMap[placesId]; ok {
				notIncomePlace += 1
			}
		}
		//sql := `SELECT count(1) not_income_place  FROM places p LEFT JOIN orders o ON o.place_id = p.id
		//		AND DATE_FORMAT( FROM_UNIXTIME( o.end_at ), '%Y-%m-%d' ) <= DATE_SUB( CURDATE( ), INTERVAL 30 DAY ) WHERE o.id IS NULL  AND p.id in(?)`
		//db := global.Orm.Debug().Raw(sql, placesIds).Find(&notIncomePlace)
		//if db.Error != nil {
		//	err = db.Error
		//}
		model.UserId = id
		model.NotIncomePlace = notIncomePlace
		list = append(list, model)
	}

	return list, err
}

func (d *StatisticalDao) StatisticsDeviceNotEarnings(usersIds []int) ([]*internalstatistics.InternalStatistics, error) {
	var list []*internalstatistics.InternalStatistics
	var useDeviceSn, notDeviceSn []string
	var err error
	//sql := `SELECT count(1) not_income_device  FROM devices d LEFT JOIN orders o ON o.device_sn = d.device_sn
	//		AND DATE_FORMAT( FROM_UNIXTIME( o.end_at ), '%Y-%m-%d' ) <= DATE_SUB( CURDATE( ), INTERVAL 30 DAY )
	//		WHERE d.state = 2 and d.place_id >0 and o.id IS NULL  and d.place_id in(?)`
	//db := global.Orm.Debug().Raw(sql, placesIds).Find(&notIncomeDevice)

	//sql := `SELECT d.device_sn  FROM devices d LEFT JOIN orders o ON o.device_sn = d.device_sn
	//		AND DATE_FORMAT( FROM_UNIXTIME( o.end_at ), '%Y-%m-%d' ) <= DATE_SUB( CURDATE( ), INTERVAL 30 DAY )
	//		WHERE d.state = 2 and d.place_id >0 and o.id IS NULL GROUP BY d.device_sn`
	sql := `SELECT device_sn FROM orders WHERE  DATE_FORMAT( FROM_UNIXTIME( end_at ), '%Y-%m-%d' ) <= DATE_SUB( CURDATE( ), INTERVAL 30 DAY ) AND is_tianhai=0 AND (is_draw<>1 or (is_draw=1 and agent_user_id in (?))) `
	db := global.Orm.Debug().Raw(sql, usersIds).Find(&useDeviceSn)

	getDeviceSql := `SELECT device_sn FROM devices WHERE state = 2 AND place_id > 0`
	global.Orm.Debug().Raw(getDeviceSql).Find(&notDeviceSn)

	if db.Error != nil {
		return nil, db.Error
	}

	deviceUseEarningsMap := map[string]string{}
	deviceNotEarningsMap := map[string]string{}

	for _, sn := range useDeviceSn {
		deviceUseEarningsMap[sn] = ""
	}

	for _, sn := range notDeviceSn {
		if _, ok := deviceUseEarningsMap[sn]; ok {

		} else {
			deviceNotEarningsMap[sn] = ""
		}
	}

	//查询没有收入的网点
	for _, id := range usersIds {
		var notIncomeDevice int64
		var userDeviceSn []string
		model := &internalstatistics.InternalStatistics{}

		placesBranchIds := NewUserDao().GetPlacesId(id).Unwrap().([]int)
		userIds := NewUserDao().QueryChildUserIds(id).Unwrap().([]int)
		placeIdArr := NewPlaceDao().GetPlaceByIds(userIds).Unwrap().([]int)

		//合并网点
		placesBranchIds = append(placesBranchIds, placeIdArr...)

		//去重网点
		placesIds := utils.RemoveRepByMap(placesBranchIds)
		getDeviceSnSql := `SELECT device_sn FROM devices WHERE place_id in(?)`
		global.Orm.Debug().Raw(getDeviceSnSql, placesIds).Find(&userDeviceSn)

		for _, sn := range userDeviceSn {
			if _, ok := deviceNotEarningsMap[sn]; ok {
				notIncomeDevice += 1
			}
		}

		model.UserId = id
		model.NotIncomeDevice = notIncomeDevice
		list = append(list, model)
	}
	return list, err
}

// 查找是否统计过
func (d *StatisticalDao) InternalIsStatistics(userId int, date string) *dingo.ErrorWrap {
	var count int64
	sql := `SELECT count(1) FROM internal_statistics WHERE user_id = ? and create_at = ? `
	db := global.Orm.Raw(sql, userId, date).Find(&count)
	return dingo.ErrorIf(db.Error, count)
}

//修改内部统计数据
func (d *StatisticalDao) UpdateInternalStatistics(m *internalstatistics.InternalStatistics) *dingo.ErrorWrap {
	db := global.Orm.Table("internal_statistics").Where("user_id = ? and create_at = ?", m.UserId, m.CreateAt).Model(&m).Updates(m)
	return dingo.ErrorIf(db.Error, true)
}

//新增内部统计数据
func (d *StatisticalDao) InsertInternalStatistics(m *internalstatistics.InternalStatistics) *dingo.ErrorWrap {
	db := global.Orm.Table("internal_statistics").Create(m)
	return dingo.ErrorIf(db.Error, true)
}

func (d *StatisticalDao) GetInternalStatisticsList(params *request.InternalStatisticsReq) *dingo.ErrorWrap {
	var (
		count  int64
		list   []*internalstatistics.InternalStatistics
		limit  = params.PageSize
		offset = params.PageSize * (params.PageNo - 1)
	)

	db := global.Orm.Debug().Table("internal_statistics")
	db.Where("is_admin  = ? ", params.IsAdmin)

	if params.LoginIsAdmin != helper.TypeNumIsAdminOperator && params.UserId == 0 {
		userIds := NewUserDao().QueryChildUserIds(params.LoginUserId).Unwrap().([]int)
		db.Where("user_id in(?)", userIds)
	}

	if params.UserId > 0 {
		db.Where("user_id = ?", params.UserId)
	}

	if params.Phone != "" {
		db.Where("phone = ?", params.Phone)
	}

	if params.UserName != "" {
		db.Where(" user_name like ?", fmt.Sprint("%", params.UserName, "%"))
	}

	if params.SelectTime != "" {
		selectTimeArr := strings.Split(params.SelectTime, ",")
		startTime := selectTimeArr[0]
		endTime := selectTimeArr[1]
		db.Where("create_at >= DATE_FORMAT(FROM_UNIXTIME(?),'%Y-%m-%d')", startTime)
		db.Where("create_at <= DATE_FORMAT(FROM_UNIXTIME(?),'%Y-%m-%d')", endTime)
	}

	db.Order("create_at desc")
	db.Limit(limit).Offset(offset).Find(&list).Limit(-1).Offset(-1).Count(&count)
	return dingo.ErrorIf(db.Error, list, count)
}
